package com.example.testdemo.util

import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.content.Context.SENSOR_SERVICE
import android.content.Intent
import android.hardware.Sensor
import android.hardware.SensorManager
import android.net.Uri
import android.os.Build
import android.telephony.TelephonyManager
import android.text.TextUtils
import android.util.Log
import com.snail.antifake.jni.EmulatorDetectUtil
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader


/**
 * Create Time:2021/1/12
 * Author: Lindanrong
 * Description: 用户判断虚拟机的类
 * 参考 https://www.codercto.com/a/34627.html
 * 参考 https://github.com/happylishang/CacheEmulatorChecker
 * 使用 雷神 夜神 逍遥 蓝叠 四种虚拟机进行检测
 */



/**
 * 检查虚拟机的文件夹是否存在
 * ps；夜神 蓝叠 检测不出来
 */
fun isEmulatorByFolderExists():Boolean{
    var isEmulation = false
    for (i in emulatorFiles){
        var file = File(i)
        if (file.exists()){
            isEmulation = true
            Log.i("EmulationUtil.kt", "isFolderExists: $i")
        }
    }
    return isEmulation
}

/**
 * Android模拟器检测，检测Android模拟器 ，获取相对真实的IMEI AndroidId 序列号 MAC地址等，
 * 作为DeviceID，应对防刷需求等 How to detect Android emulator
 * 参考 https://github.com/happylishang/CacheEmulatorChecker
 *
 * ps:这个几个模拟器都测试可以  但是可能有真机会被识别成虚拟机 详细的看对应github上的issue
 */
fun isEmulatorByX86(context: Context): Boolean {
    return EmulatorDetectUtil.isEmulator(context)
}


/**
 *  以下几个方法都为改博文中整理得出
 *  判断是否为模拟器（实测夜神通过） https://blog.csdn.net/qq_25749749/article/details/95347119?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-5.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-5.nonecase
 *
 */

/**
 * 拨打电话 判断关键字眼
 * ps： 夜神 蓝叠 检测不出来
 *  真机会被误判出来是虚拟机
 */
@SuppressLint("MissingPermission")
fun isEmulatorByTellPhone(context: Context): Boolean {
    var url = "tel:"+"123456"
    var intent = Intent()
    intent.data = Uri.parse(url)
    intent.action = Intent.ACTION_DIAL

    // 是否可以处理跳转到拨号的 Intent
    val canResolveIntent =
        intent.resolveActivity(context.packageManager) != null

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.toLowerCase().contains("vbox")
                || Build.FINGERPRINT.toLowerCase().contains("test-keys")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.getSerial().equals("unknown",true)
                || Build.getSerial().equals("android",true)
                || Build.MODEL.contains("Android SDK built for x86")
                || Build.MANUFACTURER.contains("Genymotion")
                || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
                || "google_sdk" == Build.PRODUCT
                || (context.getSystemService(Context.TELEPHONY_SERVICE)as TelephonyManager)
                    .networkOperatorName.toLowerCase() == "android"
                || !canResolveIntent
    } else {
        Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.toLowerCase().contains("vbox")
                || Build.FINGERPRINT.toLowerCase().contains("test-keys")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.SERIAL.equals("unknown",true)
                || Build.SERIAL.equals("android",true)
                || Build.MODEL.contains("Android SDK built for x86")
                || Build.MANUFACTURER.contains("Genymotion")
                || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
                || "google_sdk" == Build.PRODUCT
                || (context.getSystemService(Context.TELEPHONY_SERVICE)as TelephonyManager)
            .networkOperatorName.toLowerCase() == "android"
                || !canResolveIntent
    }
}

/**
 * 判断是否存在光传感器或者蓝牙来判断是否为模拟器
 * 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
 * @return true 为模拟器
 * ps： 夜神 蓝叠 逍遥 雷电 检测不出来
 */
fun isEmulatorByHasLightOrBluetooth(context: Context): Boolean {
    //获取光传感器
    val sensor8: Sensor? =
        (context.getSystemService(SENSOR_SERVICE) as SensorManager).getDefaultSensor(Sensor.TYPE_LIGHT) //光
    var hasLight = if (sensor8 == null) return true else false

    //获取蓝牙传感器
    val ba = BluetoothAdapter.getDefaultAdapter()
    var hasBluetooth = if (ba == null) {
        true
    } else {
        // 如果有蓝牙不一定是有效的。获取蓝牙名称，若为null 则默认为模拟器
        val name = ba.name
        TextUtils.isEmpty(name)
    }

    return hasBluetooth || hasLight
}


/**
 *根据CPU是否为电脑来判断是否为模拟器
 *返回:true 为模拟器
 * ps：夜神检测不出来
 */
fun isEmulatorByCpuName(): Boolean {
    val cpuInfo: String = readCpuInfo()
    return cpuInfo.contains("intel") || cpuInfo.contains("amd")
}

/**
 *根据CPU是否为电脑来判断是否为模拟器(子方法)
 *返回:String
 *
 */
fun readCpuInfo(): String {
    var result = ""
    try {
        val args =
            arrayOf("/system/bin/cat", "/proc/cpuinfo")
        val cmd = ProcessBuilder(*args)
        val process = cmd.start()
        val sb = StringBuffer()
        var readLine: String? = ""
        val responseReader =
            BufferedReader(InputStreamReader(process.inputStream, "utf-8"))
        while (responseReader.readLine().also({ readLine = it }) != null) {
            sb.append(readLine)
        }
        responseReader.close()
        result = sb.toString().toLowerCase()
    } catch (ex: IOException) {
    }
    return result
}



/**
 * 这个其实相当鸡肋
 *根据部分特征参数设备信息来判断是否为模拟器
 *返回:true 为模拟器
 */
fun isFeatures(): Boolean {
    return (Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.toLowerCase().contains("vbox")
            || Build.FINGERPRINT.toLowerCase().contains("test-keys")
            || Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.MODEL.contains("Android SDK built for x86")
            || Build.MANUFACTURER.contains("Genymotion")
            || Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
            || "google_sdk" == Build.PRODUCT)
}

/**
 * 这个是虚拟机存在的目录文件 但是未经过多个机型测试 不敢确定是否准确
 */
val emulatorFiles: Array<String> = arrayOf(
    "/data/youwave_id",
    "/dev/vboxguest",
    "/dev/vboxuser",
    "/mnt/prebundledapps/bluestacks.prop.orig",
    "/mnt/prebundledapps/propfiles/ics.bluestacks.prop.note",
    "/mnt/prebundledapps/propfiles/ics.bluestacks.prop.s2",
    "/mnt/prebundledapps/propfiles/ics.bluestacks.prop.s3",
    "/mnt/sdcard/bstfolder/InputMapper/com.bluestacks.appmart.cfg",
    "/mnt/sdcard/buildroid-gapps-ics-20120317-signed.tgz",
    "/mnt/sdcard/windows/InputMapper/com.bluestacks.appmart.cfg",
    "/proc/irq/9/vboxguest",
    "/sys/bus/pci/drivers/vboxguest",
    "/sys/bus/pci/drivers/vboxguest/0000:00:04.0",
    "/sys/bus/pci/drivers/vboxguest/bind",
    "/sys/bus/pci/drivers/vboxguest/module",
    "/sys/bus/pci/drivers/vboxguest/new_id",
    "/sys/bus/pci/drivers/vboxguest/remove_id",
    "/sys/bus/pci/drivers/vboxguest/uevent",
    "/sys/bus/pci/drivers/vboxguest/unbind",
    "/sys/bus/platform/drivers/qemu_pipe",
    "/sys/bus/platform/drivers/qemu_trace",
    "/sys/class/bdi/vboxsf-c",
    "/sys/class/misc/vboxguest",
    "/sys/class/misc/vboxuser",
    "/sys/devices/virtual/bdi/vboxsf-c",
    "/sys/devices/virtual/misc/vboxguest",
    "/sys/devices/virtual/misc/vboxguest/dev",
    "/sys/devices/virtual/misc/vboxguest/power",
    "/sys/devices/virtual/misc/vboxguest/subsystem",
    "/sys/devices/virtual/misc/vboxguest/uevent",
    "/sys/devices/virtual/misc/vboxuser",
    "/sys/devices/virtual/misc/vboxuser/dev",
    "/sys/devices/virtual/misc/vboxuser/power",
    "/sys/devices/virtual/misc/vboxuser/subsystem",
    "/sys/devices/virtual/misc/vboxuser/uevent",
    "/sys/module/vboxguest",
    "/sys/module/vboxguest/coresize",
    "/sys/module/vboxguest/drivers",
    "/sys/module/vboxguest/drivers/pci:vboxguest",
    "/sys/module/vboxguest/holders",
    "/sys/module/vboxguest/holders/vboxsf",
    "/sys/module/vboxguest/initsize",
    "/sys/module/vboxguest/initstate",
    "/sys/module/vboxguest/notes",
    "/sys/module/vboxguest/notes/.note.gnu.build-id",
    "/sys/module/vboxguest/parameters",
    "/sys/module/vboxguest/parameters/log",
    "/sys/module/vboxguest/parameters/log_dest",
    "/sys/module/vboxguest/parameters/log_flags",
    "/sys/module/vboxguest/refcnt",
    "/sys/module/vboxguest/sections",
    "/sys/module/vboxguest/sections/.altinstructions",
    "/sys/module/vboxguest/sections/.altinstr_replacement",
    "/sys/module/vboxguest/sections/.bss",
    "/sys/module/vboxguest/sections/.data",
    "/sys/module/vboxguest/sections/.devinit.data",
    "/sys/module/vboxguest/sections/.exit.text",
    "/sys/module/vboxguest/sections/.fixup",
    "/sys/module/vboxguest/sections/.gnu.linkonce.this_module",
    "/sys/module/vboxguest/sections/.init.text",
    "/sys/module/vboxguest/sections/.note.gnu.build-id",
    "/sys/module/vboxguest/sections/.rodata",
    "/sys/module/vboxguest/sections/.rodata.str1.1",
    "/sys/module/vboxguest/sections/.smp_locks",
    "/sys/module/vboxguest/sections/.strtab",
    "/sys/module/vboxguest/sections/.symtab",
    "/sys/module/vboxguest/sections/.text",
    "/sys/module/vboxguest/sections/__ex_table",
    "/sys/module/vboxguest/sections/__ksymtab",
    "/sys/module/vboxguest/sections/__ksymtab_strings",
    "/sys/module/vboxguest/sections/__param",
    "/sys/module/vboxguest/srcversion",
    "/sys/module/vboxguest/taint",
    "/sys/module/vboxguest/uevent",
    "/sys/module/vboxguest/version",
    "/sys/module/vboxsf",
    "/sys/module/vboxsf/coresize",
    "/sys/module/vboxsf/holders",
    "/sys/module/vboxsf/initsize",
    "/sys/module/vboxsf/initstate",
    "/sys/module/vboxsf/notes",
    "/sys/module/vboxsf/notes/.note.gnu.build-id",
    "/sys/module/vboxsf/refcnt",
    "/sys/module/vboxsf/sections",
    "/sys/module/vboxsf/sections/.bss",
    "/sys/module/vboxsf/sections/.data",
    "/sys/module/vboxsf/sections/.exit.text",
    "/sys/module/vboxsf/sections/.gnu.linkonce.this_module",
    "/sys/module/vboxsf/sections/.init.text",
    "/sys/module/vboxsf/sections/.note.gnu.build-id",
    "/sys/module/vboxsf/sections/.rodata",
    "/sys/module/vboxsf/sections/.rodata.str1.1",
    "/sys/module/vboxsf/sections/.smp_locks",
    "/sys/module/vboxsf/sections/.strtab",
    "/sys/module/vboxsf/sections/.symtab",
    "/sys/module/vboxsf/sections/.text",
    "/sys/module/vboxsf/sections/__bug_table",
    "/sys/module/vboxsf/sections/__param",
    "/sys/module/vboxsf/srcversion",
    "/sys/module/vboxsf/taint",
    "/sys/module/vboxsf/uevent",
    "/sys/module/vboxsf/version",
    "/sys/module/vboxvideo",
    "/sys/module/vboxvideo/coresize",
    "/sys/module/vboxvideo/holders",
    "/sys/module/vboxvideo/initsize",
    "/sys/module/vboxvideo/initstate",
    "/sys/module/vboxvideo/notes",
    "/sys/module/vboxvideo/notes/.note.gnu.build-id",
    "/sys/module/vboxvideo/refcnt",
    "/sys/module/vboxvideo/sections",
    "/sys/module/vboxvideo/sections/.data",
    "/sys/module/vboxvideo/sections/.exit.text",
    "/sys/module/vboxvideo/sections/.gnu.linkonce.this_module",
    "/sys/module/vboxvideo/sections/.init.text",
    "/sys/module/vboxvideo/sections/.note.gnu.build-id",
    "/sys/module/vboxvideo/sections/.rodata.str1.1",
    "/sys/module/vboxvideo/sections/.strtab",
    "/sys/module/vboxvideo/sections/.symtab",
    "/sys/module/vboxvideo/sections/.text",
    "/sys/module/vboxvideo/srcversion",
    "/sys/module/vboxvideo/taint",
    "/sys/module/vboxvideo/uevent",
    "/sys/module/vboxvideo/version",
    "/system/app/bluestacksHome.apk",
    "/system/bin/androVM-prop",
    "/system/bin/androVM-vbox-sf",
    "/system/bin/androVM_setprop",
    "/system/bin/get_androVM_host",
    "/system/bin/mount.vboxsf",
    "/system/etc/init.androVM.sh",
    "/system/etc/init.buildroid.sh",
    "/system/lib/hw/audio.primary.vbox86.so",
    "/system/lib/hw/camera.vbox86.so",
    "/system/lib/hw/gps.vbox86.so",
    "/system/lib/hw/gralloc.vbox86.so",
    "/system/lib/hw/sensors.vbox86.so",
    "/system/lib/modules/3.0.8-android-x86+/extra/vboxguest",
    "/system/lib/modules/3.0.8-android-x86+/extra/vboxguest/vboxguest.ko",
    "/system/lib/modules/3.0.8-android-x86+/extra/vboxsf",
    "/system/lib/modules/3.0.8-android-x86+/extra/vboxsf/vboxsf.ko",
    "/system/lib/vboxguest.ko",
    "/system/lib/vboxsf.ko",
    "/system/lib/vboxvideo.ko",
    "/system/usr/idc/androVM_Virtual_Input.idc",
    "/system/usr/keylayout/androVM_Virtual_Input.kl",
    "/system/xbin/mount.vboxsf",
    "/ueventd.android_x86.rc",
    "/ueventd.vbox86.rc",
    "/ueventd.goldfish.rc",
    "/fstab.vbox86",
    "/init.vbox86.rc",
    "/init.goldfish.rc",
    // ========针对原生Android模拟器 内核：goldfish=========== "/sys/module/goldfish_audio",
    "/sys/module/goldfish_sync",
    // ========针对蓝叠模拟器=========== "/data/app/com.bluestacks.appmart-1.apk",
    "/data/app/com.bluestacks.BstCommandProcessor-1.apk",
    "/data/app/com.bluestacks.help-1.apk",
    "/data/app/com.bluestacks.home-1.apk",
    "/data/app/com.bluestacks.s2p-1.apk",
    "/data/app/com.bluestacks.searchapp-1.apk",
    "/data/bluestacks.prop",
    "/data/data/com.androVM.vmconfig",
    "/data/data/com.bluestacks.accelerometerui",
    "/data/data/com.bluestacks.appfinder",
    "/data/data/com.bluestacks.appmart",
    "/data/data/com.bluestacks.appsettings",
    "/data/data/com.bluestacks.BstCommandProcessor",
    "/data/data/com.bluestacks.bstfolder",
    "/data/data/com.bluestacks.help",
    "/data/data/com.bluestacks.home",
    "/data/data/com.bluestacks.s2p",
    "/data/data/com.bluestacks.searchapp",
    "/data/data/com.bluestacks.settings",
    "/data/data/com.bluestacks.setup",
    "/data/data/com.bluestacks.spotlight",
    // ========针对逍遥安卓模拟器=========== // 虚拟化网卡和pci，可能存在误判，不可靠 // "/sys/module/virtio_net",
    // "/sys/module/virtio_pci",
    "/data/data/com.microvirt.download",
    "/data/data/com.microvirt.guide",
    "/data/data/com.microvirt.installer",
    "/data/data/com.microvirt.launcher",
    "/data/data/com.microvirt.market",
    "/data/data/com.microvirt.memuime",
    "/data/data/com.microvirt.tools",
    // ========针对Mumu模拟器=========== "/data/data/com.mumu.launcher",
    "/data/data/com.mumu.store",
    "/data/data/com.netease.mumu.cloner"
)